<!-- 图片单个上传 -->
<template>
  <div class="upload-signle-img">
    <div :class="['upload-icon', {'upload-icon-loading': isUploading}]" v-if="!imageUrl || isUploading">
      <span @click="handleChangeImg">
        <i :class="[isUploading ? 'el-icon-loading' : 'el-icon-plus']"></i>
      </span>
    </div>
    <div class="img-wrap">
      <img :src="imageUrl" alt="">
    </div>
    <div class="opr-wrap" v-if="imageUrl">
      <span>
        <i class="el-icon-delete" @click="handleRemoveImg"></i>
        <i @click="handleChangeImg" :class="[isUploading ? 'el-icon-loading' : 'el-icon-plus']"></i>
      </span>
    </div>
    <input class="up-input" ref="filElem" :accept="acceptList" type="file" @change="getFile" :disabled="isUploading">
  </div>
</template>

<script>
import axios from 'axios'
import { GetPictureUploadSignData } from '@/api/common'
export default {
  name: 'imgSignleUpload',
  components: {},
  data () {
    return {
      acceptList: ['image/gif', 'image/jpeg', 'image/png', 'image/jpg', 'image/jpeg'],
      uploading: false,
      isUploading: false,
      host: '',
      ossData: {},
      imageUrl: '',
      vistUrl: '', // 图片上传后前置域名
      dialogVisible: false,
      dialogImageUrl: '',
      errorNum: 0 // 提示错误次数
    }
  },
  props: {
    value: {
      type: String,
      default: ''
    },
    // 限制的尺寸
    limitSize: {
      type: Object,
      default: () => {
        return {
          width: 0,
          height: 0
        }
      }
    },
    // 限制的大小
    limitBigSmall: {
      type: Number,
      default: 10
    },
    // 图片限制尺寸忽略范围
    limitSizeRange: {
      type: Number,
      default: 50
    }
  },
  watch: {},
  computed: {},
  mounted () {
    this.imageUrl = this.value
  },
  methods: {
    handleChangeImg () {
      this.$refs.filElem.dispatchEvent(new MouseEvent('click'))
    },
    getFile (files) {
      const file = files.target.files[0]
      // 判断文件大小
      const imgSizeMb = (file.size / 1024 / 1024).toFixed(2) // 上传图片的大小(M)
      const isPassMb = imgSizeMb <= this.limitBigSmall // 是否小于等于我们允许的大小
      if (!isPassMb) {
        this.errorMsg(`上传图片大小为${imgSizeMb}M，超过${this.limitBigSmall}M的限制，请重新上传...`)
        return
      }

      // 判断文件尺寸
      let limitWidth = this.limitSize.width
      let limitHeight = this.limitSize.height
      const limitSizeRange = this.limitSizeRange // 忽略范围
      const that = this

      let img = new Image()
      img.onload = function () {
        // 上传图片文件大小尺寸与限制尺寸的绝对值差大于 忽略范围 不通过
        if (limitWidth && Math.abs(img.width - limitWidth) >= limitSizeRange) {
          that.errorMsg(`上传的图片尺寸要求等于或大于${limitWidth}x${limitHeight}!`)
        } else if (limitHeight && Math.abs(img.height - limitHeight) >= limitSizeRange) {
          that.errorMsg(`上传的图片尺寸要求等于或大于${limitWidth}x${limitHeight}!`)
        } else {
          that.getSignData(file)
        }
      }
      img.onerror = function () {
        that.errorMsg('图片尺寸不符合，请重新上传....')
      }
      let _URL = window.URL || window.webkitURL
      img.src = _URL.createObjectURL(file)
    },
    handleRemoveImg () {
      this.imageUrl = ''
    },
    getSignData (file) {
      this.isUploading = true
      GetPictureUploadSignData().then(res => {
        const data = res.data
        this.host = data.host
        let fileName = file.name
        let suffix = fileName.split('.')[1]
        const moment = new Date().getTime()
        fileName = `${moment}.${suffix}`
        this.ossData = {
          'key': `${data.dir}/${fileName}`,
          'policy': data.policy,
          'OSSAccessKeyId': data.accessKeyId,
          'signature': data.signature
        }
        // 图片上传后前置域名
        this.vistUrl = data.vistUrl
        this.ossUpload(this.host, file, this.ossData, this.vistUrl)
      }).catch(() => {
        this.uploading = false
        this.host = ''
        this.ossData = {}
      })
    },
    ossUpload (host, file, ossData, vistUrl, item) {
      let ossFormData = new FormData()
      for (const key in ossData) {
        ossFormData.append(key, ossData[key])
      }
      ossFormData.append('file', file)
      const url = vistUrl + ossData.key

      axios({
        url: host,
        method: 'POST',
        data: ossFormData,
        headers: { 'Content-Type': 'multipart/form-data' }
      }).then(res => {
        this.isUploading = false
        this.imageUrl = url
        this.upEmitValue()
        this.removeInputFileValue()
      }).catch(errors => {
        this.removeInputFileValue()
        this.isUploading = false
        this.$message.error('上传失败！')
      })
    },
    removeInputFileValue () {
      this.firstUpImgName = ''
      this.$refs.filElem.value = ''
    },
    errorMsg (message, type = 'warning', duration = 3) {
      this.$message({
        message: message,
        type: type,
        duration: duration * 1000
      })
      this.errorNum++
    },
    upEmitValue (val) {
      this.$emit('input', this.imageUrl)
    }
  }
}

</script>
<style lang='scss' scoped>
$borderRadius: 3px;
$Percentage: 98%;
.upload-signle-img {
  &:hover {
    .opr-wrap {
      display: block;
    }
    border-color: rgb(51, 153, 255);
  }
  border-radius: $borderRadius;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  width: 100px;
  height: 100px;
  border: 1px dashed rgb(192, 204, 218);
  box-sizing: border-box;
  .up-input {
    position: absolute;
    z-index: -1;
  }
  .upload-icon {
    width: $Percentage;
    height: $Percentage;
    position: absolute;
    z-index: 2;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    span {
      display: block;
      width: 100%;
      height: 100%;
      display: flex;
      align-self: center;
      align-items: center;
      justify-content: center;
    }
    i {
      font-size: 30px;
      color: rgb(51, 153, 255);
    }
  }
  .upload-icon-loading {
    background: rgba(243, 243, 243, 0.24);
  }
  .img-wrap {
    width: $Percentage;
    height: $Percentage;
    position: absolute;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    border-radius: $borderRadius;
    img {
      border-radius: $borderRadius;
      width: 100%;
      height: 100%;
      object-fit: fill;
    }
  }
  .opr-wrap {
    display: none;
    background: rgba(0, 0, 0, 0.5);
    border-radius: $borderRadius;
    transition: all 0.2s ease-in-out;
    width: $Percentage;
    height: $Percentage;
    position: absolute;
    z-index: 2;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    span {
      display: block;
      width: 100%;
      height: 100%;
      display: flex;
      align-self: center;
      align-items: center;
      justify-content: center;
    }

    i {
      font-size: 20px;
      color: rgba(255, 255, 255, 0.85);
      transition: all 0.1s ease-in-out;
      &:hover {
        color: white;
        transform: scale(1.1);
      }
    }
  }
}
</style>
